﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Collections.ObjectModel;

namespace Cid
{
    using Cid.Models;

    /// <summary>
    /// Interaction logic for Display.xaml
    /// </summary>
    public partial class Display : Window
    {
        private int numPerPage;
        private int page;
		private int hours = 4;
		private System.Windows.Threading.DispatcherTimer pageTimer;

        private ObservableCollection<ConferenceEvent> events;
        public Display()
        {
            InitializeComponent();
            numPerPage = 3;
            page = 1;

			this.hours = Convert.ToInt32(ConfigurationManager.AppSettings["hours"]);
			this.WindowStartupLocation = WindowStartupLocation.CenterOwner;

			this.eventList.MouseEnter += new MouseEventHandler(eventList_MouseEnter);
			this.eventList.MouseLeave += new MouseEventHandler(eventList_MouseLeave);
        }

		public double StackWidth
		{
			get { return (this.eventList.Width - 250); }
		}

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.events = new ObservableCollection<ConferenceEvent>();

			this.Bind(ConferenceEvent.FindByRelevantTime(this.hours).ToList());
			

           

            System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
            timer.Interval = new TimeSpan(0, 5, 0);
            timer.IsEnabled = true;
			timer.Start();


            timer.Tick += delegate(object owner, EventArgs args)
            {
				List<ConferenceEvent> list = ConferenceEvent.FindByRelevantTime(this.hours).ToList();
                this.Bind(list);
            };

			this.pageTimer = new System.Windows.Threading.DispatcherTimer();
			this.pageTimer.Interval = new TimeSpan(0, 0, 12);
			this.pageTimer.IsEnabled = true;
			this.pageTimer.Tick += new EventHandler(pageTimer_Tick);
			this.pageTimer.Start();


            GotoPage(page);
            this.Prev.IsEnabled = false;

            if (this.events.Count > 0)
            {
                this.eventList.SelectedIndex = 0;
                this.DetailsStackPanel.DataContext = events[0];
            }
        }

		void eventList_MouseLeave(object sender, MouseEventArgs e)
		{
			if (this.pageTimer != null)
				this.pageTimer.Start();
		}

		void eventList_MouseEnter(object sender, MouseEventArgs e)
		{
			if (this.pageTimer != null)
				this.pageTimer.Stop();
		}


		private delegate void NavigateCallback();

		private void Navigate() 
		{
			if (this.Dispatcher.Thread != System.Threading.Thread.CurrentThread)
			{
				this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background,
					new NavigateCallback(this.Navigate));
				return;
			}

			if (this.events.Count > page * numPerPage)
				GotoPage(++page);
			else
			{
				this.page = 1;
				GotoPage(page);
			}
		}

		void pageTimer_Tick(object sender, EventArgs e)
		{
			this.Navigate();
		}

        protected delegate void BindCallback(object args);

        private void Bind(object args)
        {
            if (this.Dispatcher.Thread != System.Threading.Thread.CurrentThread)
            {
                this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.DataBind,
                    new BindCallback(Bind), args);
                return;
            }

            List<ConferenceEvent> list = args as List<ConferenceEvent>;
            this.events.Clear();
            list.Each(o => this.events.Add(o));
        }


        private void GotoPage(int page)
        {
            // page 2
            int start = numPerPage * (page - 1);
            // start = 2 * (2 - 1)
            // start = 2

            int end = start + numPerPage;
            // end = 2 + 2;
            // end = 4;
            // events.count = 3

            if (end > events.Count) // 3 > 4
            {
                end = events.Count; // end = 3
                this.page = (events.Count / numPerPage) + 1; // page = 2
            }

            this.eventList.ItemsSource = this.events.Skip(start).Take(end - start);
            if (this.eventList.Items.Count > 0)
            {
                this.eventList.SelectedIndex = 0;
                ShowDetail(events[start]);
            }

			if ((page * numPerPage) >= this.events.Count)
				this.Next.IsEnabled = false;
			else
				this.Next.IsEnabled = true;

			if (page == 1)
				this.Prev.IsEnabled = false;
			else
				this.Prev.IsEnabled = true;

        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
                Close();
        }

        private void ShowDetail(ConferenceEvent conferenceEvent)
        {
            Storyboard fade = (Storyboard)this.FindResource("FadeDetails");

            fade.Completed += new EventHandler(delegate
            {
                this.DetailsStackPanel.DataContext = conferenceEvent;
                Storyboard show = (Storyboard)this.FindResource("ShowDetails");
                show.Begin(this.DetailsStackPanel);
            });

            fade.Begin(this.DetailsStackPanel);
        }

        private void eventList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.eventList.SelectedIndex < 0)
                return;
            ConferenceEvent conferenceEvent = events[((this.page - 1) * numPerPage) + this.eventList.SelectedIndex];

            ShowDetail(conferenceEvent);
        }

        private void oscText_Loaded(object sender, RoutedEventArgs e)
        {
            Animate((TextBlock)sender);
        }

        private void Animate(TextBlock txtBlock)
        {
            Storyboard storyboard = new Storyboard();
            storyboard.Duration = TimeSpan.FromSeconds(15);
            storyboard.RepeatBehavior = RepeatBehavior.Forever;

            if (txtBlock.TextEffects != null)
                txtBlock.TextEffects.Clear();
            else
                txtBlock.TextEffects = new TextEffectCollection();

            for (int i = 0; i < txtBlock.Text.Length; i++)
            {
                // so define the effect
                TextEffect effect = new TextEffect();
                TranslateTransform translateTransform = new TranslateTransform();
                effect.PositionStart = i;
                effect.PositionCount = 1;

                effect.Transform = translateTransform;

                txtBlock.TextEffects.Add(effect);

                // This animation sets the value from 0 to 20 of SOMETHING. All it does is 
                // do the automatic timelining of setting that value for the given duration
                // and we apply that value setter to a particular property later (using the
                // property path object)
                DoubleAnimation animation = new DoubleAnimation(0, -3, TimeSpan.FromSeconds(.2));
                animation.AccelerationRatio = 0.5;
                animation.DecelerationRatio = 0.5;
                animation.AutoReverse = true;
                //animation.RepeatBehavior = RepeatBehavior.Forever;
                animation.BeginTime = TimeSpan.FromSeconds(i * 0.1);

                // which object to apply the storyboard animation to
                Storyboard.SetTargetName(animation, txtBlock.Name);
                // which property to apply the storyboard animation to
                Storyboard.SetTargetProperty(animation, new PropertyPath(String.Format("TextEffects[{0}].Transform.Y", i)));

                storyboard.Children.Add(animation);
            }
            storyboard.Begin(txtBlock);
        }

        private void oscText_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Animate((TextBlock)sender);
        }

        private void eventList_KeyDown(object sender, KeyEventArgs e)
        {
            this.eventList.SelectedIndex = -1;
            events = new ObservableCollection<ConferenceEvent>(ConferenceEvent.Find().ToList());
            this.eventList.ItemsSource = events;
        }

        private void Next_Click(object sender, RoutedEventArgs e)
        {
            GotoPage(++this.page);
            if (page > 1)
                this.Prev.IsEnabled = true;
            if (this.page * numPerPage > events.Count)
                this.Next.IsEnabled = false;
        }

        private void CallStoryboard(string storyboardName)
        {
            try
            {
                Storyboard storyboard = (Storyboard)this.FindResource(storyboardName);
                storyboard.Begin(this);
            }
            catch (Exception)
            {
            }
        }


        private void Prev_Click(object sender, RoutedEventArgs e)
        {
            if (--this.page < 1)
                this.page = 1;
            else
            {
                this.Next.IsEnabled = true;
                GotoPage(this.page);
                if (this.page == 1)
                    this.Prev.IsEnabled = false;
            }
        }
    }
}
